/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.biz.modular.blogpostcategory.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.biz.modular.blogpostcategory.entity.BlogPostCategory;
import vip.xiaonuo.biz.modular.blogpostcategory.mapper.BlogPostCategoryMapper;
import vip.xiaonuo.biz.modular.blogpostcategory.param.BlogPostCategoryAddParam;
import vip.xiaonuo.biz.modular.blogpostcategory.param.BlogPostCategoryEditParam;
import vip.xiaonuo.biz.modular.blogpostcategory.param.BlogPostCategoryIdParam;
import vip.xiaonuo.biz.modular.blogpostcategory.param.BlogPostCategoryPageParam;
import vip.xiaonuo.biz.modular.blogpostcategory.service.BlogPostCategoryService;
import vip.xiaonuo.common.consts.DictConst;
import vip.xiaonuo.common.consts.GlobalConst;
import vip.xiaonuo.common.enums.CommonExceptionEnum;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.exception.ServiceException;
import vip.xiaonuo.common.page.CommonPageRequest;

import java.util.List;
import java.util.Map;

/**
 * 文章分类Service接口实现类
 *
 * @author skwyl
 * @date 2023/10/02 16:30
 **/
@Service
public class BlogPostCategoryServiceImpl extends ServiceImpl<BlogPostCategoryMapper, BlogPostCategory> implements BlogPostCategoryService {

    @Override
    public Page<BlogPostCategory> page(BlogPostCategoryPageParam blogPostCategoryPageParam) {
        QueryWrapper<BlogPostCategory> queryWrapper = new QueryWrapper<>();
        //全路径搜索搜索包括子类
        if (ObjectUtil.isNotEmpty(blogPostCategoryPageParam.getFullPath())) {
            queryWrapper.lambda().likeRight(BlogPostCategory::getFullPath, blogPostCategoryPageParam.getFullPath());
        }
        if (ObjectUtil.isNotEmpty(blogPostCategoryPageParam.getTitle())) {
            queryWrapper.lambda().like(BlogPostCategory::getTitle, blogPostCategoryPageParam.getTitle());
        }
        if (ObjectUtil.isNotEmpty(blogPostCategoryPageParam.getCode())) {
            queryWrapper.lambda().like(BlogPostCategory::getCode, blogPostCategoryPageParam.getCode());
        }

        if (ObjectUtil.isAllNotEmpty(blogPostCategoryPageParam.getSortField(), blogPostCategoryPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(blogPostCategoryPageParam.getSortOrder());
            queryWrapper.orderBy(true, blogPostCategoryPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(blogPostCategoryPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(BlogPostCategory::getFullPath).orderByDesc(BlogPostCategory::getCreateTime);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(BlogPostCategoryAddParam blogPostCategoryAddParam) {
        BlogPostCategory blogPostCategory = BeanUtil.toBean(blogPostCategoryAddParam, BlogPostCategory.class);
        blogPostCategory.setFlgChild(DictConst.YES_OR_NO_NO.getValue());
        this.save(blogPostCategory);
        //判断 如果父类ID不为Root则 判断父类ID是否存在
        if (StrUtil.isNotEmpty(blogPostCategoryAddParam.getParentId()) && !ObjectUtil.equals(GlobalConst.ROOT, blogPostCategoryAddParam.getParentId())) {
            BlogPostCategory parent = this.queryEntity(blogPostCategoryAddParam.getParentId());
            if (ObjectUtil.isNull(parent)) {
                CommonExceptionEnum res = CommonExceptionEnum.ERROR415;
                throw new ServiceException(res.getCode(), "请选择正确的父类ID");
            }
            //修改父分类数据 如flg_child
            if (!ObjectUtil.equals(DictConst.YES_OR_NO_YES.getValue(), parent.getFlgChild())) {
                parent.setFlgChild(DictConst.YES_OR_NO_YES.getValue());
                this.updateById(parent);
            }
            //修改子分类数据
            blogPostCategory.setFlgTop(DictConst.YES_OR_NO_NO.getValue());
            blogPostCategory.setFullPath(StrUtil.format("{}-{}", parent.getFullPath(), blogPostCategory.getId()));
            blogPostCategory.setFullNamePath(StrUtil.format("{}-{}", parent.getFullNamePath(), blogPostCategory.getTitle()));
        } else {
            blogPostCategory.setParentId(GlobalConst.ROOT);
            blogPostCategory.setFlgTop(DictConst.YES_OR_NO_YES.getValue());
            blogPostCategory.setFullPath(StrUtil.format("{}-{}", GlobalConst.ROOT, blogPostCategory.getId()));
            blogPostCategory.setFullNamePath(StrUtil.format("{}-{}", GlobalConst.ROOT, blogPostCategory.getTitle()));
        }
        this.updateById(blogPostCategory);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(BlogPostCategoryEditParam blogPostCategoryEditParam) {
        //判断当前ID是否等于父类ID
        if (ObjectUtil.equals(blogPostCategoryEditParam.getParentId(), blogPostCategoryEditParam.getId())) {
            CommonExceptionEnum res = CommonExceptionEnum.ERROR415;
            throw new ServiceException(res.getCode(), "当前分类的父类ID为当前ID哦");
        }
        BlogPostCategory blogPostCategory = this.queryEntity(blogPostCategoryEditParam.getId());
        String tempFullPath = blogPostCategory.getFullPath();//备份原始的全路径
        BeanUtil.copyProperties(blogPostCategoryEditParam, blogPostCategory);
        //判断 如果父类ID不为Root则 判断父类ID是否存在
        if (StrUtil.isNotEmpty(blogPostCategoryEditParam.getParentId()) && !ObjectUtil.equals(GlobalConst.ROOT, blogPostCategoryEditParam.getParentId())) {
            BlogPostCategory parent = this.queryEntity(blogPostCategoryEditParam.getParentId());
            if (ObjectUtil.isNull(parent)) {
                CommonExceptionEnum res = CommonExceptionEnum.ERROR415;
                throw new ServiceException(res.getCode(), "请选择正确的父类ID");
            }
            //修改父分类数据 如flg_child
            if (!ObjectUtil.equals(DictConst.YES_OR_NO_YES.getValue(), parent.getFlgChild())) {
                parent.setFlgChild(DictConst.YES_OR_NO_YES.getValue());
                this.updateById(parent);
            }
            //修改子分类数据
            blogPostCategory.setFlgTop(DictConst.YES_OR_NO_NO.getValue());
            blogPostCategory.setFullPath(StrUtil.format("{}-{}", parent.getFullPath(), blogPostCategory.getId()));
            blogPostCategory.setFullNamePath(StrUtil.format("{}-{}", parent.getFullNamePath(), blogPostCategory.getTitle()));
        } else {
            blogPostCategory.setParentId(GlobalConst.ROOT);
            blogPostCategory.setFlgTop(DictConst.YES_OR_NO_YES.getValue());
            blogPostCategory.setFullPath(StrUtil.format("{}-{}", GlobalConst.ROOT, blogPostCategory.getId()));
            blogPostCategory.setFullNamePath(StrUtil.format("{}-{}", GlobalConst.ROOT, blogPostCategory.getTitle()));
        }
        this.updateById(blogPostCategory);
        //更新分类的fullpath
        if (ObjectUtil.equals(DictConst.YES_OR_NO_YES.getValue(), blogPostCategory.getFlgChild())) {
            //获取所有子类
            QueryWrapper<BlogPostCategory> childWrapper = new QueryWrapper<>();
            childWrapper.lambda().likeRight(BlogPostCategory::getFullPath, tempFullPath + "-");
            List<BlogPostCategory> childList = this.list(childWrapper);
            childList.forEach(o -> {
                //将子类的Fullpath 替换掉前缀 并更新
                o.setFullPath(StrUtil.replace(o.getFullPath(), tempFullPath, blogPostCategory.getFullPath()));
                this.updateById(o);
            });
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<BlogPostCategoryIdParam> blogPostCategoryIdParamList) {
        List<String> ids = CollStreamUtil.toList(blogPostCategoryIdParamList, BlogPostCategoryIdParam::getId);
        ids.forEach(s -> {
            BlogPostCategory blogPostCategory = this.queryEntity(s);
            if (ObjectUtil.isNull(blogPostCategory)) {
                CommonExceptionEnum res = CommonExceptionEnum.ERROR500;
                throw new ServiceException(res.getCode(), "id:{},的分类不存在", s);
            }
            //删除当前分类 并且删除子类
            QueryWrapper<BlogPostCategory> deleteWrapper = new QueryWrapper<>();
            deleteWrapper.lambda().likeRight(BlogPostCategory::getFullPath, blogPostCategory.getFullPath());
            this.remove(deleteWrapper);
        });
    }

    @Override
    public BlogPostCategory detail(BlogPostCategoryIdParam blogPostCategoryIdParam) {
        return this.queryEntity(blogPostCategoryIdParam.getId());
    }

    @Override
    public BlogPostCategory queryEntity(String id) {
        BlogPostCategory blogPostCategory = this.getById(id);
        if (ObjectUtil.isEmpty(blogPostCategory)) {
            throw new CommonException("文章分类不存在，id值为：{}", id);
        }
        return blogPostCategory;
    }

    //作用与后台不需要缓存
    @Override
    public JSONArray allTree() {
        JSONArray jsonArray = new JSONArray();
        //获取所有顶级分类
        QueryWrapper<BlogPostCategory> rootWrapper = new QueryWrapper<>();
        rootWrapper.lambda().eq(BlogPostCategory::getFlgTop, DictConst.YES_OR_NO_YES.getValue());
        List<BlogPostCategory> rootList = this.list(rootWrapper);
        //遍历顶级分类 并递归获取子分类 以及子分类的分类
        rootList.forEach(o -> {
            //将查询的顶级分类转换为Map
            Map<String, Object> rootMap = BeanUtil.beanToMap(o);
            //查询子类递归
            recursionGetTree(o, rootMap);
            jsonArray.add(rootMap);
        });
        return jsonArray;
    }

    /**
     * 递归获取顶级分类的子类
     */
    private void recursionGetTree(BlogPostCategory o, Map<String, Object> rootMap) {
        //判断是否有子类 如果没有则退出方法 取反防止null的存在
        if (ObjectUtil.isNull(o) || ObjectUtil.isNull(rootMap) || rootMap.isEmpty() || !ObjectUtil.equals(DictConst.YES_OR_NO_YES.getValue(), o.getFlgChild())) {
            return;
        }
        JSONArray childArray = new JSONArray();
        //根据ID查询子类
        QueryWrapper<BlogPostCategory> childWrapper = new QueryWrapper<>();
        childWrapper.lambda().eq(BlogPostCategory::getParentId, o.getId());
        List<BlogPostCategory> childList = this.list(childWrapper);
        childList.forEach(child -> {
            Map<String, Object> childMap = BeanUtil.beanToMap(child);
            childArray.add(childMap);
            recursionGetTree(child, childMap);
        });
        //将递归到的子类添加到当前分类的子集
        rootMap.put("children", childArray);
    }
}
